package com.myBlog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.myBlog.domain.ResponseResult;
import com.myBlog.domain.dto.RoleDTO;
import com.myBlog.domain.entity.Menu;
import com.myBlog.domain.entity.Role;
import com.myBlog.domain.entity.RoleMenu;
import com.myBlog.domain.vo.MenuTreeVo;
import com.myBlog.domain.vo.PageVo;
import com.myBlog.domain.vo.RoleVo;
import com.myBlog.enums.AppHttpCodeEnum;
import com.myBlog.mapper.RoleMapper;
import com.myBlog.service.MenuService;
import com.myBlog.service.RoleMenuService;
import com.myBlog.service.RoleService;
import com.myBlog.utils.BeanCopyUtils;
import com.myBlog.utils.SystemConverter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.myBlog.enums.AppHttpCodeEnum.*;

/**
 * 角色信息表(Role)表服务实现类
 *
 * @author makejava
 * @since 2023-03-19 10:16:31
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    @Resource
    private RoleMenuService roleMenuService;
    @Resource
    private RoleMapper roleMapper;
    @Override
    public List<String> selectRoleKeyByUser(Long id) {
        //判断是否为管理员，如果是，返回集合中只需要有admin
        if (id == 1L) {
            ArrayList<String> roleKeys = new ArrayList<>();
            roleKeys.add("admin");
            return roleKeys;
        }

        //否则查询用户所具有的角色信息

        return getBaseMapper().selectRoleByUserId(id);
    }

    /**
     * 分页条件查询
     * @param pageNum
     * @param pageSize
     * @param roleName
     * @param status
     * @return
     */
    @Override
    public ResponseResult<PageVo> list(Integer pageNum, Integer pageSize, String roleName, String status) {
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();

        wrapper.like(StringUtils.hasText(roleName), Role::getRoleName, roleName);
        wrapper.eq(StringUtils.hasText(status), Role::getStatus, status);
        wrapper.select(Role::getId, Role::getRoleName, Role::getRoleKey, Role::getRoleSort, Role::getStatus, Role::getCreateTime);
        wrapper.orderByAsc(Role::getRoleSort);
        Page<Role> rolePage = new Page<>(pageNum, pageSize);
        page(rolePage, wrapper);
        PageVo pageVo = new PageVo(rolePage.getRecords(), rolePage.getTotal());

        return ResponseResult.okResult(pageVo);
    }

    /**
     * 修改状态
     * @param roleDTO
     * @return
     */
    @Override
    public ResponseResult changeStatus(RoleDTO roleDTO) {

        Role role = BeanCopyUtils.copyBean(roleDTO, Role.class);
        if ("admin".equals(role.getRoleName())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.ADMIN_NOT_CHANGE);
        }
        updateById(role);

        return ResponseResult.okResult();
    }

    /**
     * 根据id查询权限信息
     * @param roleId
     * @return
     */
    @Override
    public ResponseResult getRoleInfo(Long roleId) {
        Role role = getById(roleId);
        RoleVo roleVo = BeanCopyUtils.copyBean(role, RoleVo.class);
        return ResponseResult.okResult(roleVo);
    }

    /**
     * 添加权限
     * @param roleDTO
     * @return
     */
    @Override
    @Transactional
    public ResponseResult addRole(RoleDTO roleDTO) {
//        1.根据角色名判断当前角色是否存在
        if (!this.judgeRole(roleDTO.getRoleName())) {
            return ResponseResult.errorResult(ROLE_INFO_EXIST);
        }
        //        1.根据权限名判断当前角色是否存在
        if (!this.judgeRoleKey(roleDTO.getRoleKey())) {
            return ResponseResult.errorResult(ROLEKEY_INFO_EXIST);
        }
        //        2.获取到当前角色的菜单权限列表
        List<Long> menuIds = roleDTO.getMenuIds();

//        3.将RoleDto对象转换为Role对象
        Role role = BeanCopyUtils.copyBean(roleDTO, Role.class);
        save(role);

        //4.遍历menuIds，添加到sys_role_menu表中
        menuIds.stream()
                .map(menuId -> roleMenuService
                        .save(new RoleMenu(role.getId(), menuId)));

        return ResponseResult.okResult();
    }

    /**
     * 修改权限
     * @param roleDTO
     * @return
     */
    @Override
    @Transactional
    public ResponseResult updateRole(RoleDTO roleDTO) {
        if (!StringUtils.hasText(roleDTO.getRoleName()) ||
                !StringUtils.hasText(roleDTO.getRoleKey()) ||
                !StringUtils.hasText(String.valueOf(roleDTO.getStatus())) ||
                !StringUtils.hasText(roleDTO.getRemark()) ||
                !StringUtils.hasText(String.valueOf(roleDTO.getRoleSort()))) {
            return ResponseResult.errorResult(CONTENT_IS_BLANK);
        }


        List<Long> menuIds = roleDTO.getMenuIds();
        //  将RoleDto对象转换为Role对象
        Role role = BeanCopyUtils.copyBean(roleDTO, Role.class);
        updateById(role);
        //  根据roleId移除sys_role_menu表中的数据
//        roleMenuService.removeById(role.getId());

        for (Long menuId : menuIds) {
            roleMenuService.save(new RoleMenu(role.getId(), menuId));
        }
        return ResponseResult.okResult();
    }

    /**
     * 根据id删除权限
     * @param roleId
     * @return
     */
    @Override
    @Transactional
    public ResponseResult delete(Long roleId) {
        LambdaQueryWrapper<RoleMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleMenu::getRoleId, roleId);
        roleMenuService.remove(wrapper);
        removeById(roleId);
        return ResponseResult.okResult();
    }

    /**
     * 查询出所有角色
     *
     * @return {@link ResponseResult}
     */
    @Override
    public ResponseResult getListAllRole() {
        List<Role> roles = roleMapper.selectList(null);
        return ResponseResult.okResult(roles);
    }

    /**
     * 判断角色是否存在
     *
     * @param roleName
     * @return
     */
    public boolean judgeRole(String roleName) {
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Role::getRoleName, roleName);
        Role role = getOne(queryWrapper);
        if (Objects.isNull(role)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 判断权限是否存在
     *
     * @param roleKey
     * @return
     */
    public boolean judgeRoleKey(String roleKey) {
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Role::getRoleKey, roleKey);
        Role role = getOne(queryWrapper);
        if (Objects.isNull(role)) {
            return true;
        } else {
            return false;
        }
    }

}

